
(function(undefined){

console.log(3);

if (typeof FLT === 'undefined') {
    window.FLT={};
}

$.extend(FLT, {
    CMP_CLASS: 'flt-cmp',
    CMP_CLASS_PREFIX: 'ftype-',
    CMP:{
        // register an FLT component.
        reg: function(ftype, parent, obj, deepcopy){
        
            obj.ftype = ftype;
            
            for (var k in deepcopy) {
                obj[k] = $.extend({}, FLT.CMP.Button.prototype[k], deepcopy[k])
            }
            
            this[ftype] = this[parent].extend(obj);
            
        }
    },
    CANVAS:'body'
});

/* Component Class 
 * represents non-geometry data associated with components.
 */
FLT.CMP.Cmp = Class.extend({
    
    ftype: 'Cmp',
    
    init:function(opts){
        $.extend(this, opts || {});
        return this;
    },
    
    html: '<div></div>',
    
    // default attributes to apply to all children.
    defaults: {
        ftype:'Cmp'
    },
    
    get_item: function(opts) {
        var _match;
        $.each(this.items, function(idx,item) {
            for (var k in opts) {
                if (item[k] !== opts[k]) return;
            }
            _match = item;
        });
        return _match;
    },
    
    items: [],
    
    // returns jQuery dom element.
    // should only be called by draw() and render().
    render: function() {
        
        if (!this.$) {
            var i = 0, it, $H = $(this.html);
            
            // apply renderable attributes.
            if (this.css) $H.css(this.css);
            if (this.attr) $H.attr(this.attr);
            if (this.text) $H.text(this.text);
            if (this.name) $H.addClass('name-'+this.name);
            
            // recursively render child components.
            for (;i < this.items.length;i++) {
            
                it = this.items[i];
                it.parent=this;
                
                // for strings, don't create component end - just html.
                if (typeof it === 'string') {
                        $H.append(it);
                } else {
                    // if we get anything besides a component, assume it's a 
                    // spec for a component & use it to create a component.
                    if (!(it instanceof FLT.CMP.Cmp)) {
                        it = $.extend({}, this.defaults, it);
                        this.items[i] = new FLT.CMP[ it.ftype ]( it );
                    }
                    $H.append(this.items[i].render());
                }
            }
            this.$ = $H
                .addClass(FLT.CMP_CLASS)
                .addClass(FLT.CMP_CLASS_PREFIX + this.ftype)
                .data('cmp',this);
        }
        return this.$;
        
    },
    
    // if not already done, render the component and place on the canvas.
    draw: function() {
    
        if (!this.$) {
            this.$ = this.render().appendTo(FLT.CANVAS);
        } else {
            this.$.show();
        }
        
        return this;
    },
    
    // destroy the current widget markup and redraw it from scratch.
    redraw: function(){
        this.$.remove();
        this.$ = null;
        this.draw();
    }
});


FLT.CMP.reg('Block', 'Cmp', {
    html: "<div></div>"
});

FLT.CMP.reg('Widget','Block',{
    render: function() {
        return this._super(arguments);
    }
}); // end Widget.

FLT.CMP.reg('Button', 'Widget', {
    css: {
        cursor:'pointer'
    }
});

evt = 0;

FLT.EVENTS = {

    init: function(){
        // Bind FLT object event handlers.
        FLT.$.click(function(e) {
            // keep rack of previously showing washable elements
            FLT.$pending_wash = $(".ftype-Menu:visible");
            if (FLT.EVENTS.delegate(e) !== false) {
                // hide washable elements.
                FLT.$pending_wash.hide();
            }
        });

        // Bind FLT object event handlers.
        FLT.$.bind('mouseover mousedown mouseout',FLT.EVENTS.delegate);    
    },
    
    // calls handlers on all components who are parents to the event target.
    // returns false if any callee returns false.
    delegate: function(e){
        var rv;
        $(e.target)
            .add($(e.target).parents()).filter('.'+FLT.CMP_CLASS)
            .each(function(){
            
                evt++;
                //console.info(evt+' events logged');
                
                var cmp = $(this).cmp();
                if (cmp[e.type]) {
                    if (cmp[e.type].call(cmp, e, this) === false) rv=false;
                }
            });
        return rv;
    }
};

// Processing which requires the document to be ready.
$(function(){
    FLT.$ = $(document);
    FLT.EVENTS.init();
});

$.fn.cmp = function(){ return $(this).data('cmp'); }

}))(); // end module


